package com.hyw.trace.utils;

import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Objects;

public final class ReflectionUtils {

  /*
   * 用于防止反射生成对应的实例，也不允许任何继承
   */
  private ReflectionUtils() {
    throw new IllegalStateException("Utility class");
  }

  /**
   * 用于判断一个对象是不是复杂结构的类型
   * <p>
   * Null, Number，Character,CharSequence,Boolean 在此处都会被认为是基础类型（包括其包装类） <br>
   * 考虑到一些场景上需要JSON序列化,只有复杂对象结构才需要，而普通的包装类则不需要
   * 
   * @param obj
   *          待验证参数
   * @return 是否属于原始类型
   */
  public static boolean isPrimitive(Object obj) {
    boolean isPrimitive = false;
    if (Objects.isNull(obj) || obj instanceof Number || obj instanceof Character || obj instanceof CharSequence
        || obj instanceof Boolean) {
      isPrimitive = true;
    }
    return isPrimitive;
  }

  public static <T> T newInstanceOf(Class<T> clz) {
    try {
      return clz.newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
      throw new IllegalArgumentException(e);
    }
  }

  public static <T> T newInstanceOf(Class<T> clz, Class<?> argClz, Object argValue) {
    try {
      return clz.getConstructor(argClz).newInstance(argValue);
    } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
        | IllegalArgumentException | InvocationTargetException ex) {
      throw new IllegalArgumentException(ex);
    }

  }

  @SuppressWarnings("rawtypes")
  public static Class getClass(Type type, int i) {
    if (type instanceof ParameterizedType) { // 处理泛型类型
      return getGenericClass((ParameterizedType) type, i);
    } else if (type instanceof TypeVariable) {
      return getClass(((TypeVariable) type).getBounds()[0], 0); // 处理泛型擦拭对象
    } else {// class本身也是type，强制转型
      return (Class) type;
    }
  }

  @SuppressWarnings("rawtypes")
  public static Class getGenericClass(ParameterizedType parameterizedType, int i) {
    Object genericClass = parameterizedType.getActualTypeArguments()[i];
    if (genericClass instanceof ParameterizedType) { // 处理多级泛型
      return (Class) ((ParameterizedType) genericClass).getRawType();
    } else if (genericClass instanceof GenericArrayType) { // 处理数组泛型
      return (Class) ((GenericArrayType) genericClass).getGenericComponentType();
    } else if (genericClass instanceof TypeVariable) { // 处理泛型擦拭对象
      return getClass(((TypeVariable) genericClass).getBounds()[0], 0);
    } else {
      return (Class) genericClass;
    }
  }
}
